package wsp.dailymarket.shopping;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.sql.DataSource;
import wsp.dailymarket.auth.AuthenticationBean;

/**
 * Represents the display of a single invoice
 * @author Matt
 */
@ManagedBean(name = "invoiceBean")
@RequestScoped
public class InvoiceBean {

	@Resource(name = "jdbc/dmderby")
	private DataSource ds;
	@ManagedProperty(value = "#{authenticationBean}")
	private AuthenticationBean authBean;
	private int invoiceId;
	private int status;
	private Timestamp ts_placed;
	private ArrayList<InvoiceLineItem> lineItems;
	public static final int STATUS_INVALID = 0x0F00; // This object does not contain a valid order
	public static final int STATUS_COMPLETED = 0x0F01; // All deals are ready to download
	public static final int STATUS_CANCELLED = 0x0F02; // Entire order cancelled
	public static final int STATUS_DEALS_PENDING = 0x0F03; // Some deals are timed and have not expired yet

	public InvoiceBean() {
		invoiceId = 0;
		ts_placed = null;
		lineItems = new ArrayList<InvoiceLineItem>();
		status = STATUS_INVALID;
	}

	public void populate(int id, Timestamp ts, int status) {
		this.invoiceId = id;
		this.ts_placed = ts;
		this.status = status;
	}

	public void lookupById(int id) {
		this.invoiceId = id;
		try {
			Connection conn = null;
			try {
				conn = ds.getConnection();
				Statement stmt = conn.createStatement();
				String sql = "SELECT * FROM APP.ORDERS WHERE CLIENT_ID = '" + authBean.getAuthentication().getUserID() + "' AND ID = " + id;
				ResultSet rs = stmt.executeQuery(sql);
				if (rs.next()) {
					this.ts_placed = rs.getTimestamp("TS_PLACED");
					this.status = rs.getInt("ORDER_STATUS");
					this.buildLineItems();
				} else {
					FacesMessage msg = new FacesMessage();
					msg.setSeverity(FacesMessage.SEVERITY_ERROR);
					msg.setSummary("The order could not be found!");
					FacesContext.getCurrentInstance().addMessage(null, msg);
				}
			} finally {
				if (conn != null) {
					conn.close();
				}
			}
		} catch (SQLException ex) {
			ex.printStackTrace(System.err);
			FacesMessage msg = new FacesMessage();
			msg.setSeverity(FacesMessage.SEVERITY_FATAL);
			msg.setSummary("Database Error!");
			FacesContext.getCurrentInstance().addMessage(null, msg);
		}

	}

	public void buildLineItems() throws SQLException {
		this.lineItems.clear();
		Connection conn = null;
		try {
			conn = ds.getConnection();
			Statement stmt = conn.createStatement();
			String sql = "SELECT"
					+ "	ord.ID as line_item_id,"
					+ "	ord.ORDER_ID,"
					+ "	ord.status,"
					+ "	del.* "
					+ "FROM APP.DEAL_ORDERS AS ord "
					+ "LEFT JOIN"
					+ "	(SELECT"
					+ "		APP.DEALS.*,"
					+ "		APP.CLIENTS.COMPANYNAME,"
					+ "		APP.CATEGORIES.CATEGORY_NAME"
					+ "		FROM APP.DEALS"
					+ "		INNER JOIN APP.CLIENTS"
					+ "			ON APP.DEALS.COMPANYID=APP.CLIENTS.CLIENT_ID"
					+ "		LEFT OUTER JOIN APP.CATEGORIES"
					+ "			ON APP.DEALS.CATEGORY_ID = APP.CATEGORIES.ID) as del"
					+ "	ON del.ID = ord.DEAL_ID "
					+ "WHERE ord.ORDER_ID = " + this.invoiceId;
			ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				// Prepare line item data
				InvoiceLineItem newItem = new InvoiceLineItem();
				newItem.setLineItemId(rs.getInt("line_item_id"));
				newItem.setStatus(rs.getInt("STATUS"));
				newItem.getDeal().populate(
						rs.getInt("ID"),
						rs.getString("COMPANYID"),
						rs.getString("COMPANYNAME"),
						rs.getString("SHORTDESC"),
						rs.getString("LONGDESC"),
						rs.getFloat("UNITPRICE"),
						rs.getInt("MINIMUMQTY"),
						rs.getInt("MAXIMUMQTY"),
						rs.getInt("MINUSERQTY"),
						rs.getInt("MAXUSERQTY"),
						rs.getInt("TIMED") == 1,
						rs.getTimestamp("STARTTIME"),
						rs.getTimestamp("ENDTIME"),
						rs.getInt("DEFAULT_IMAGE"),
						rs.getInt("CATEGORY_ID"),
						rs.getString("CATEGORY_NAME"));
				// Prepare code(s) for line item
				String code_sql = "SELECT * FROM APP.DEAL_CODES WHERE DEAL_ORDER_ID = " + newItem.getLineItemId();
				Statement stmt2 = conn.createStatement();
				ResultSet code_rs = stmt2.executeQuery(code_sql);
				while (code_rs.next()) {
					InvoiceDealCode newCode = new InvoiceDealCode();
					newCode.populate(
							code_rs.getInt("ID"),
							code_rs.getString("CODE_DATA"),
							code_rs.getFloat("PRICE_POINT"),
							code_rs.getInt("CODE_USED") == 1,
							authBean.getAuthentication().getUserID());
					newItem.getCodes().add(newCode);
				}
				this.lineItems.add(newItem);
			}
		} finally {
			if (conn != null) {
				conn.close();
			}
		}
	}

	public void setAuthBean(AuthenticationBean newValue) {
		this.authBean = newValue;
	}

	public ArrayList<InvoiceLineItem> getLineItems() {
		return this.lineItems;
	}

	public void setInvoiceId(int newValue) {
		this.lookupById(newValue);
	}

	public int getInvoiceId() {
		return this.invoiceId;
	}

	public String getTimePlacedString() {
		if (ts_placed != null) {
			return new Date(ts_placed.getTime()).toString();
		} else {
			return "";
		}
	}

	public int getStatus() {
		return this.status;
	}

	public String getStatusString() {
		switch (this.status) {
			case InvoiceBean.STATUS_COMPLETED:
				return "Completed";
			case InvoiceBean.STATUS_DEALS_PENDING:
				return "Deal Pending";
			case InvoiceBean.STATUS_CANCELLED:
				return "Cancelled";
			case InvoiceBean.STATUS_INVALID:
			default:
				return "Invalid Order";
		}
	}

	public String getStatusStyle() {
		switch (this.status) {
			case InvoiceBean.STATUS_COMPLETED:
				return "status good";
			case InvoiceBean.STATUS_DEALS_PENDING:
				return "status warn";
			case InvoiceBean.STATUS_CANCELLED:
				return "status error";
			case InvoiceBean.STATUS_INVALID:
			default:
				return "status fatal";
		}
	}

	public boolean isRenderable() {
		return this.status != InvoiceBean.STATUS_INVALID;
	}
}
